home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / v7n11.arc / PP711.ARC / SCANTD.ASM < prev    next >
Assembly Source File  |  1988-06-21  |  11KB  |  352 lines

  1.         name    scantd
  2.         title   SCANTD.ASM --- time & date input conversion
  3.         page    55,132
  4. ;
  5. ;
  6. ; SCANTD.ASM --- Convert ASCII times and dates
  7. ;                to binary in MS-DOS format.
  8. ;
  9. ; Copyright (c) 1988 Ziff Communications Co.
  10. ; PC Magazine * Ray Duncan
  11. ;
  12. ; This module contains two public routines:
  13. ;
  14. ;
  15. ; SCANTIME      convert ASCII time to binary
  16. ;
  17. ; Call with:    DS:SI = address of string
  18. ;
  19. ; Returns:      Carry = Set if bad time
  20. ;               or
  21. ;               Carry = Clear if good time
  22. ;               CH    = hour
  23. ;               CL    = minute
  24. ;               DH    = second
  25. ;               DL    = hundredths
  26. ;               DS:SI = address+1 of terminator
  27. ;               other registers preserved
  28. ;
  29. ;
  30. ; SCANDATE      convert ASCII date to binary
  31. ;
  32. ; Call with:    DS:SI = address of string
  33. ;
  34. ; Returns:      Carry = Set if bad date
  35. ;               or
  36. ;               Carry = Clear if good date
  37. ;               CX    = year (1980+)
  38. ;               DH    = month (1-12)
  39. ;               DL    = day (1-31)
  40. ;               DS:SI = address+1 of terminator
  41. ;               other registers preserved
  42. ;
  43.  
  44. DGROUP  group   _DATA
  45.  
  46.  
  47. _DATA   segment word public 'DATA'
  48.  
  49. n1      dw      0               ; first converted field
  50. n2      dw      0               ; second converted field
  51. n3      dw      0               ; third converted field
  52.  
  53. dlmtab  db      '/-.'           ; valid date delimiters
  54. dlmtab_len equ $-dlmtab         ; length of table
  55.  
  56. tlmtab  db      ':.'            ; valid time delimiters
  57. tlmtab_len equ $-tlmtab         ; length of table
  58.  
  59.                                 ; date format table
  60. dftab   dw      mdy             ; code 0 = mon/day/year
  61.         dw      dmy             ; code 1 = day/mon/year
  62.         dw      ymd             ; code 2 = year/mon/day
  63.  
  64. dfptr   dw      0               ; becomes address of
  65.                                 ; mdy, dmy, or ymd
  66.  
  67. mdy     dw      n2              ; day
  68.         dw      n1              ; month
  69.         dw      n3              ; year
  70.  
  71. dmy     dw      n1              ; day
  72.         dw      n2              ; month
  73.         dw      n3              ; year
  74.  
  75. ymd     dw      n3              ; day
  76.         dw      n2              ; month
  77.         dw      n1              ; year
  78.  
  79. daytab  dw      31,28,31        ; days in month
  80.         dw      30,31,30
  81.         dw      31,31,30
  82.         dw      31,30,31
  83.  
  84. cbuff   db      34 dup (0)      ; current country info
  85.  
  86. _DATA   ends
  87.  
  88.  
  89. _TEXT   segment word public 'CODE'
  90.  
  91.         assume  cs:_TEXT,ds:DGROUP
  92.  
  93.         extrn   atoi:near       ; we need ATOI routine
  94.  
  95.         public  scantime        ; make these routines
  96.         public  scandate        ; available to Linker
  97.  
  98.  
  99. scantime proc   near            ; convert ASCII time to binary
  100.  
  101.         push    ax              ; save registers
  102.         push    bx
  103.         push    di
  104.         push    es
  105.  
  106.         call    getctry         ; get internationalization
  107.                                 ; info if first call
  108.  
  109.         call    chknum          ; convert first field
  110.         jc      scant9          ; jump, bad number
  111.         mov     n1,ax           ; save result
  112.  
  113.         mov     al,[si-1]       ; check time delimiter
  114.         call    chktlm
  115.         jc      scant9          ; jump if no good
  116.  
  117.         call    chknum          ; convert second field
  118.         jc      scant9          ; jump, bad number
  119.         mov     n2,ax           ; save result
  120.  
  121.         mov     n3,0            ; force seconds = 0
  122.  
  123.         mov     al,[si-1]       ; another field present?
  124.         call    chktlm          ; if no delimiter,
  125.         jc      scant1          ; assume seconds absent
  126.  
  127.         call    chknum          ; convert third field
  128.         jc      scant9          ; jump, bad number
  129.         mov     n3,ax           ; save value
  130.  
  131. scant1:                         ; validate entry
  132.  
  133.         cmp     word ptr n1,0   ; hours must be 0-23
  134.         jc      scant9          ; jump, bad hour
  135.         cmp     word ptr n1,24
  136.         cmc
  137.         jc      scant9          ; jump, bad hour
  138.  
  139.         cmp     word ptr n2,0   ; minutes must be 0-59
  140.         jc      scant9          ; jump, bad minute
  141.         cmp     word ptr n2,60
  142.         cmc
  143.         jc      scant9          ; jump, bad minute
  144.  
  145.         cmp     word ptr n3,0   ; seconds must be 0-59
  146.         jc      scant9          ; jump, bad second
  147.         cmp     word ptr n3,60
  148.         cmc
  149.         jc      scant9          ; jump, bad second
  150.  
  151.                                 ; load the results...
  152.         mov     ch,byte ptr n1  ; hours
  153.         mov     cl,byte ptr n2  ; minutes
  154.         mov     dh,byte ptr n3  ; seconds
  155.         mov     dl,0            ; hundredths always = 0
  156.  
  157. scant9:                         ; common exit point
  158.         pop     es              ; restore registers
  159.         pop     di
  160.         pop     bx
  161.         pop     ax
  162.         ret                     ; return to caller
  163.  
  164. scantime endp
  165.  
  166.  
  167. scandate proc   near            ; convert ASCII date to binary
  168.  
  169.         push    ax              ; save registers
  170.         push    bx
  171.         push    di
  172.         push    es
  173.  
  174.         call    getctry         ; get internationalization
  175.                                 ; info if first call
  176.  
  177.         call    chknum          ; convert first field
  178.         jc      scand9          ; jump, bad number
  179.         mov     n1,ax           ; save result
  180.  
  181.         mov     al,[si-1]       ; get delimiter
  182.         call    chkdlm          ; and check it
  183.         jc      scand9          ; exit, bad delimiter
  184.  
  185.  
  186.         call    chknum          ; convert second field
  187.         jc      scand9          ; jump, bad number
  188.         mov     n2,ax           ; save result
  189.  
  190.         mov     al,[si-1]       ; get delimiter
  191.         call    chkdlm          ; and check it
  192.         jc      scand9          ; exit, bad delimiter
  193.  
  194.         call    chknum          ; convert third field
  195.         jc      scand9          ; jump, bad number
  196.         mov     n3,ax           ; and save result
  197.  
  198.                                 ; validate entry and
  199.                                 ; load results...
  200.  
  201.         mov     bx,dfptr        ; point to year
  202.         mov     bx,[bx+4]       ; year must be 80-99
  203.         cmp     word ptr [bx],80
  204.         jc      scand9          ; jump, bad year
  205.         cmp     word ptr [bx],100
  206.         cmc
  207.         jc      scand9          ; jump, bad year
  208.         mov     cx,[bx]         ; load year and correct
  209.         add     cx,1900         ; to range 1980-1999
  210.  
  211.                                 ; adjust days/month table
  212.         mov     daytab+2,28     ; assume not leap year
  213.         test    word ptr [bx],3 ; is it a leap year?
  214.         jnz     scand1          ; jump, not multiple of 4
  215.         mov     daytab+2,29     ; fix table for leap year
  216.  
  217. scand1: mov     bx,dfptr        ; point to month
  218.         mov     bx,[bx+2]
  219.         cmp     word ptr [bx],1 ; month must be 1-12
  220.         jc      scand9          ; jump, bad month
  221.         cmp     word ptr [bx],13
  222.         cmc
  223.         jc      scand9          ; jump, bad month
  224.         mov     dh,byte ptr [bx]; load month result
  225.         mov     di,[bx]         ; also prepare to index
  226.         dec     di              ; into days/month table
  227.         shl     di,1
  228.  
  229.         mov     bx,dfptr        ; point to day
  230.         mov     bx,[bx]
  231.         cmp     word ptr [bx],1 ; day must be >= 1
  232.         jc      scand9          ; jump, bad day
  233.         mov     ax,[di+daytab]  ; get max day for this
  234.                                 ; month from table
  235.         cmp     ax,[bx]
  236.         jc      scand9          ; jump, bad day
  237.         mov     dl,byte ptr [bx]; load day result
  238.  
  239. scand9:                         ; common exit point
  240.         pop     es              ; restore registers
  241.         pop     di
  242.         pop     bx
  243.         pop     ax
  244.         ret                     ; return to caller
  245.  
  246. scandate endp
  247.  
  248.  
  249. chkdlm  proc    near            ; check date delimiter
  250.                                 ; call with:
  251.                                 ; AL = character to check
  252.                                 ; returns:
  253.                                 ; Carry = Clear if OK
  254.                                 ; Carry = Set if not OK
  255.  
  256.         push    ds              ; make delimiter table
  257.         pop     es              ; addressable
  258.         mov     di,offset DGROUP:dlmtab
  259.         mov     cx,dlmtab_len
  260.  
  261.         repne scasb             ; compare to table
  262.  
  263.         je      chkd9           ; jump if match found
  264.                                 ; (Carry is cleared)
  265.  
  266.         stc                     ; else force Carry = set
  267.  
  268. chkd9:  ret                     ; back to caller
  269.  
  270. chkdlm  endp
  271.  
  272.  
  273. chktlm  proc    near            ; check time delimiter
  274.                                 ; call with:
  275.                                 ; AL = character to check
  276.                                 ; returns:
  277.                                 ; Carry = Clear if OK
  278.                                 ; Carry = Set if not OK
  279.  
  280.         push    ds              ; make delimiter table
  281.         pop     es              ; addressable
  282.         mov     di,offset DGROUP:tlmtab
  283.         mov     cx,tlmtab_len
  284.  
  285.         repne scasb             ; compare to table
  286.  
  287.         je      chkt9           ; jump if match found
  288.                                 ; (Carry is cleared)
  289.  
  290.         stc                     ; else force Carry = set
  291.  
  292. chkt9:  ret                     ; back to caller
  293.  
  294. chktlm  endp
  295.  
  296.  
  297. chknum  proc    near            ; check for valid numeric
  298.                                 ; field and convert it
  299.                                 ; call with:
  300.                                 ; DS:DI = ASCII field
  301.                                 ; returns:
  302.                                 ; Carry = clear if OK
  303.                                 ; AX    = value of field
  304.                                 ; or
  305.                                 ; Carry = set if not OK
  306.  
  307.                                 ; check if >= '0'
  308.         cmp     byte ptr [si],'0'
  309.         jb      chkn1           ; jump, bad digit
  310.  
  311.                                 ; check if <= '9'
  312.         cmp     byte ptr [si],'9'+1
  313.         cmc                     ; invert Carry flag
  314.         jc      chkn1           ; jump, bad digit
  315.  
  316.         call    atoi            ; convert field and
  317.         clc                     ; clear carry flag
  318.  
  319. chkn1:  ret                     ; back to caller
  320.  
  321. chknum  endp
  322.  
  323.  
  324. getctry proc    near            ; get country information
  325.  
  326.         test    dfptr,-1        ; did we already get info?
  327.         jnz     getc2           ; if we did, just exit
  328.  
  329.         mov     ax,3000h        ; Fxn. 30h = get DOS vers.
  330.         int     21h             ; transfer to MS-DOS
  331.  
  332.         or      al,al           ; is it version 1.x?
  333.         jz      getc1           ; yes, jump
  334.  
  335.         mov     ax,3800h        ; get current country info
  336.         mov     dx,offset DGROUP:cbuff
  337.         int     21h             ; transfer to MS-DOS
  338.  
  339. getc1:                          ; get date code (default=0)
  340.         mov     bx,word ptr cbuff
  341.         shl     bx,1            ; extract pointer to
  342.         mov     ax,[bx+dftab]   ; date format table
  343.         mov     dfptr,ax
  344.  
  345. getc2:  ret                     ; back to caller
  346.  
  347. getctry endp
  348.  
  349. _TEXT   ends
  350.  
  351.         end
  352.